#region Microsoft Public License
/*
 * (c) Copyright Chenjun Wu. http://utablesdk.codeplex.com
 * 
 * This source is subject to the Microsoft Public License (Ms-PL).
 * Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
 * All other rights reserved.
 */
#endregion

using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Media;
using UTable.Input;
using UTable.Input.MultiTouch;
using UTable.Objects.Handlers;

namespace UTable.Objects.Controls
{
    public class ControlBaseImpl: IControl
    {
        #region Private Fields
        private String _id;
        private ControlInfo _info;
        private FrameworkElement _owner;
        private bool _isHitTestEnabled = true;
		private MultiTouchProcessor _processor = new MultiTouchProcessor();
        #endregion

		#region Internal Methods
        internal static void OverrideMetadata(Type type)
        {
            /*
            OverrideMetadata(FrameworkElement.WidthProperty, type);
            OverrideMetadata(FrameworkElement.HeightProperty, type);
            OverrideMetadata(FrameworkElement.MinWidthProperty, type);
            OverrideMetadata(FrameworkElement.MinHeightProperty, type);
            OverrideMetadata(FrameworkElement.MaxWidthProperty, type);
            OverrideMetadata(FrameworkElement.MaxHeightProperty, type);
            OverrideMetadata(FrameworkElement.OpacityProperty, type);
            OverrideMetadata(FrameworkElement.VisibilityProperty, type);
            OverrideMetadata(FrameworkElement.IsHitTestVisibleProperty, type);
            OverrideMetadata(FrameworkElement.ClipProperty, type);
            OverrideMetadata(FrameworkElement.RenderTransformProperty, type);
            OverrideMetadata(Panel.ZIndexProperty, type);*/

            // OverrideMetadata(FrameworkElement.ActualWidthProperty, type);
            // OverrideMetadata(FrameworkElement.ActualHeightProperty, type);
        }

        internal static void OverrideMetadata(DependencyProperty property, Type type)
        {
            property.OverrideMetadata(type, new FrameworkPropertyMetadata(new PropertyChangedCallback(PropertyChanged)));
        }

        internal static void PropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            (sender as IControl).Info.OnPropertyChanged(args.Property, args.OldValue, args.NewValue);
        }

        public ControlBaseImpl(FrameworkElement owner)
        {
            _owner = owner;
            _id = UTableHelper.GetNewId();
            _info = new ControlInfo();
            _info.Control = _owner as IControl;
            _info.ID = this.ID;
            _info.Visibility = _owner.Visibility;
            _info.IsHitTestVisible = _owner.IsHitTestVisible;
            _info.IsHitTestEnabled = this.IsHitTestEnabled;
            _info.Opacity = _owner.Opacity;
            _owner.Loaded += new RoutedEventHandler(_owner_Loaded);
        }

        void _owner_Loaded(object sender, RoutedEventArgs e)
        {
            if (UTableHelper.CurrentVisualTree != null && UTableHelper.CurrentVisualTree is UObject)
                _info.Entity = (UTableHelper.CurrentVisualTree as UObject).Entity;
        }

        #endregion

        #region IControl Members

        public ControlInfo Info
        {
            get { return _info; }
        }

		public UTable.Objects.Handlers.MultiTouchProcessor MultiTouchProcessor
		{
			get { return _processor; }
		}

        internal event LayoutPropertyChangedEventHandler LayoutPropertyChanged;

        #endregion

        #region IVisualNode Members

        public string ID
        {
            get { return _id; }
        }

        public new double Width
        {
            get
            {
                if (double.IsNaN(_owner.Width) || _owner.Width == 0.0)
                    return _owner.ActualWidth;
                else
                    return _owner.Width;
            }
            set
            {
                _owner.Width = value;
                // Info.Fresh();
            }
        }

        public new double Height
        {
            get
            {
                if (double.IsNaN(_owner.Height) || _owner.Height == 0.0)
                    return _owner.ActualHeight;
                else
                    return _owner.Height;
            }
            set
            {
                _owner.Height = value;
                // Info.Fresh();
            }
        }

        public Geometry Clip { get; set; }

        public Visibility Visibility { get; set; }

        internal bool IsHitTestEnabled
        {
            get { return _isHitTestEnabled; }
            set { 
                _isHitTestEnabled = value;
                _info.IsHitTestVisible = value;
            }
        }

        public bool IsHitTestVisible
        {
            get { return IsHitTestEnabled && _owner.IsHitTestVisible; }
            set { _owner.IsHitTestVisible = value; }
        }

        public double Opacity { get; set; }

        #endregion

        #region IInputNode Members

        public void RaiseEvent(UTable.Input.InputEventArgs e)
        {
            if (InputReceived != null)
            {
                InputReceived(e);
            }
            OnInputReceived(e);
        }

        public void OnInputReceived(UTable.Input.InputEventArgs args)
        {

        }

        public bool CaptureFinger(int fingerId)
        {
            bool captured = UTableHelper.CaptureFinger(this._owner as IControl, fingerId, false);
            if (captured)
            {
                // raise the finger capture event
                if (GotFingerCapture != null)
                {
                    FingerEventArgs args = new FingerEventArgs();
                    args.FingerID = fingerId;
                    GotFingerCapture(this, args);
                }
            }
            return captured;
        }

        public bool UncaptureFinger(int fingerId)
        {
            bool uncaptured = UTableHelper.UncaptureFinger(this._owner as IControl, fingerId);

            if (uncaptured && LostFingerCapture != null)
            {
                FingerEventArgs args = new FingerEventArgs();
                args.FingerID = fingerId;
                LostFingerCapture(this, args);
            }

            return uncaptured;
        }

        public event FingerEventHandler GotFingerCapture;

        public event FingerEventHandler LostFingerCapture;

        public event InputEventHandler InputReceived;

        #endregion
    }
}
